
class QueryCondition {
  /**
   * 查询条件构造
   * @param field 字段
   * @param rule  规则
   * @param val {string|Array|number}
   */
  constructor(field, rule, val,fieldPy = null) {
    this._field = field
    this._rule = rule
    this._val = val
    this._fieldPy = fieldPy
  }

  get field() {
    return this._field
  }

  get rule() {
    return this._rule
  }

  get val() {
    return this._val
  }

  get fieldPy() {
    return this._fieldPy
  }
}

class OrderCondition {
  constructor(field, rule) {
    this._field = field
    this._rule = rule
  }

  get field() {
    return this._field
  }

  get rule() {
    return this._rule
  }
}

class QueryWrapper {
  constructor() {
    this._queryConditions = []
    this._orderConditions = []
  }

  /** 从JSON 对象中转换 */
  from(obj) {
    if (typeof obj !== 'object') {
      return this
    }
    if (obj._queryConditions) {
      this._queryConditions.push(...obj._queryConditions)
    }
    if (obj._orderConditions) {
      this._orderConditions.push(...obj._orderConditions)
    }
    return this
  }

  get queryConditions() {
    return this._queryConditions
  }

  get orderConditions() {
    return this._orderConditions
  }

  /**
   * 等于
   * @param field
   * @param val
   */
  eq(field, val, condition = true) {
    if (condition) {
      this._queryConditions.push(new QueryCondition(field, 'eq', val))
    }
    return this
  }

  ne(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'ne', val))
    return this
  }

  gt(field, val, condition = true) {
    if (condition) {
      this._queryConditions.push(new QueryCondition(field, 'gt', val))
    }
    return this
  }

  ge(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'ge', val))
    return this
  }

  lt(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'lt', val))
    return this
  }

  le(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'le', val))
    return this
  }

  in(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'in', val))
    return this
  }

  notIn(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'not_in', val))
    return this
  }

  notInSql(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'not_in_sql', val))
    return this
  }

  notLikeAll(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'not_like_all', val))
    return this
  }

  /**
   * 区间条件
   * @param field
   * @param val {Array}
   */
  between(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'between', val))
    return this
  }

  like(field, val, fieldPinyin) {
    this._queryConditions.push(new QueryCondition(field, 'like', val, fieldPinyin))
    return this
  }

  likeLeft(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'like_left', val))
    return this
  }

  likeRight(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'like_right', val))
    return this
  }

  isNull(field) {
    this._queryConditions.push(new QueryCondition(field, 'is_null', 1))
    return this
  }

  isNotNull(field) {
    this._queryConditions.push(new QueryCondition(field, 'is_not_null', 1))
    return this
  }

  orlike(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'or_like', val))
    return this
  }


  or(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'or', val))
    return this
  }


  // and (a in(1) or b in(2))
  andOrIn(field, val) {
    this._queryConditions.push(new QueryCondition(field, 'and_or_in', val))
    return this
  }

  orderByAsc(...fields) {
    this._orderBy('asc', fields)
  }

  orderByDesc(...fields) {
    this._orderBy('desc', ...fields)
  }

  orderBy(rule, ...fields) {
    this._orderBy(rule, ...fields)
  }

  _orderBy(rule, ...fields) {
    if (fields == null || !Array.isArray(fields)) {
      return this
    }
    if (rule === 'descending') {
      rule = 'desc'
    } else if (rule === 'ascending') {
      rule = 'asc'
    }
    for (const field of fields) {
      this._orderConditions.push(new OrderCondition(field, rule))
    }
  }
}

const queryWrappers = {
  newWrapper() {
    return new QueryWrapper()
  },
  getWrapperClass() {
    return QueryWrapper
  },
  /**
   * 检测 1 != 1  条件
   * @param wrapper {QueryWrapper}
   */
  detectOneNeOne(wrapper) {
    if (!wrapper || !(wrapper instanceof this.getWrapperClass())) {
      return false
    }
    let {queryConditions = []} = wrapper
    for (const condition of queryConditions) {
      let {field, rule, val} = condition
      if (rule != 'ne') {
        continue
      }
      if (field == '1' && val == '1') {
        return true
      }
    }
    return false
  }
}

export default queryWrappers
